﻿using Iesi.Collections.Generic;
using System.Collections;
using System.Collections.Concurrent;
using System.Diagnostics;
using System.IO.MemoryMappedFiles;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Windows;
using Point = System.Drawing.Point;

namespace Moyu后台服务
{
    /// <summary>
    /// Interaction logic for MainWindow.xaml
    /// </summary>
    public partial class MainWindow : Window
    {
        public MainWindow()
        {
            InitializeComponent();

            Process[] processcollection = Process.GetProcessesByName(System.Windows.Forms.Application.CompanyName);

            // 如果该程序进程数量大于 1 ，则说明该程序已经运行
            if (processcollection.Length > 1)
            {
                Debug.WriteLine("发现已运行的实例，进行替换...");
                // 找到并关闭其他实例
                foreach (Process process in processcollection)
                {
                    if (process.Id != Process.GetCurrentProcess().Id)
                    {
                        try
                        {
                            // 尝试优雅关闭
                            if (!process.CloseMainWindow())
                            {
                                // 如果优雅关闭失败，强制终止
                                Thread.Sleep(500);
                                process.Kill();
                            }
                            process.WaitForExit(1000); // 等待进程退出
                            Debug.WriteLine($"已关闭进程: {process.Id}");
                        }
                        catch (Exception ex)
                        {
                            Debug.WriteLine($"关闭进程 {process.Id} 时出错: {ex.Message}");
                        }
                    }
                }
                // 等待确保其他实例已关闭
                Thread.Sleep(200);
            }
            Thread.CurrentThread.Priority = ThreadPriority.AboveNormal;
            键鼠.钩子.Start();
            this.Hide();
        }

        internal class 键鼠
        {

            private const int MOUSEEVENTF_LEFTDOWN = 0x0002;
            private const int MOUSEEVENTF_LEFTUP = 0x0004;
            private const int MOUSEEVENTF_RIGHTDOWN = 0x0008;
            private const int MOUSEEVENTF_RIGHTUP = 0x0010;
            private const int MOUSEEVENTF_MIDDLEDOWN = 0x0020;
            private const int MOUSEEVENTF_MIDDLEUP = 0x0040;
            private const int MOUSEEVENTF_WHEEL = 0x0800;

            public static class 钩子
            {
                private const int WH_KEYBOARD_LL = 13;
                private const int WH_MOUSE_LL = 14;

                // 键盘按键常量
                private const int WM_KEYDOWN = 0x100;
                private const int WM_KEYUP = 0x101;
                private const int WM_SYSKEYDOWN = 0x104;
                private const int WM_SYSKEYUP = 0x105;

                // 鼠标移动常量
                private const int WM_MOUSEMOVE = 0x200;

                // 鼠标按键常量
                private const int WM_LBUTTONDOWN = 0x201;
                private const int WM_LBUTTONUP = 0x202;
                private const int WM_RBUTTONDOWN = 0x204;
                private const int WM_RBUTTONUP = 0x205;
                private const int WM_MBUTTONDOWN = 0x207;
                private const int WM_MBUTTONUP = 0x208;

                // 鼠标滚轮常量
                private const int WM_MOUSEWHEEL = 522;

                private static IntPtr _keyboardHookHandle = IntPtr.Zero; // 键盘钩子句柄
                private static LowLevelKeyboardProc _keyboardHookProc = null; // 键盘钩子委托
                private static IntPtr _mouseHookHandle = IntPtr.Zero; // 鼠标钩子句柄
                private static LowLevelMouseProc _mouseHookProc = null; // 鼠标钩子委托

                public static event Action<System.Collections.Generic.Dictionary<Keys, DateTime>> 返回组合键;
                public static event Action<Keys, bool> 键盘Click; // 键盘按下事件
                public static event Action<Point> MouseMove; // 鼠标移动事件
                public static event Action<MouseButtons> MouseDown; // 鼠标按下事件
                public static event Action<MouseButtons> MouseUP; // 鼠标弹起事件
                public static event Action<Keys> MouseWheel; // 鼠标滚轮事件


                public static void Start()
                {
                    后台服务();
                    _keyboardHookProc = new LowLevelKeyboardProc(KeyboardProc);
                    _keyboardHookHandle = SetWindowsHookEx(WH_KEYBOARD_LL, _keyboardHookProc, IntPtr.Zero, 0);

                    //注册鼠标事件
                    鼠标移动.初始化();
                    _mouseHookProc = new LowLevelMouseProc(MouseProc);
                    _mouseHookHandle = SetWindowsHookEx(WH_MOUSE_LL, _mouseHookProc, IntPtr.Zero, 0);
                }
                public static void Stop()
                {
                    UnhookWindowsHookEx(_keyboardHookHandle);
                    UnhookWindowsHookEx(_mouseHookHandle);
                }

                private static ConcurrentQueue<Action> 后台任务s = new ConcurrentQueue<Action>();
                public static void 后台服务()
                {
                    Thread t1 = new(() =>
                    {
                        Thread.CurrentThread.Priority = ThreadPriority.AboveNormal;
                        do
                        {
                            while (后台任务s.TryDequeue(out var item))
                                item();
                            Thread.Sleep(1);
                        } while (true);
                    });
                    t1.SetApartmentState(ApartmentState.STA);
                    t1.IsBackground = true;
                    t1.Start();
                }

                // 键盘按键状态字典
                private static List<键盘按键.Data> 键盘按键s = new();
                private static Dictionary<int, bool> keyPressed = new();
                [MethodImpl(MethodImplOptions.AggressiveOptimization | MethodImplOptions.AggressiveInlining)]
                private static IntPtr KeyboardProc(int nCode, int wParam, nint lParam)
                {
                    if (wParam == WM_KEYDOWN || wParam == WM_SYSKEYDOWN)
                    {
                        int keys = Marshal.ReadInt32(lParam);
                        if (!keyPressed.ContainsKey(keys) || !keyPressed[keys])
                            action(Marshal.ReadInt32(lParam), true);
                    }
                    else
                        action(Marshal.ReadInt32(lParam), false);
                    return CallNextHookEx(_keyboardHookHandle, nCode, wParam, lParam);
                    [MethodImpl(MethodImplOptions.AggressiveOptimization | MethodImplOptions.AggressiveInlining)]
                    void action(int keys, bool keydown)
                    {
                        keyPressed[keys] = keydown;
                        键盘按键.Data data = new(keys);

                        if (keydown)
                            键盘按键s.Add(data);
                        else
                            键盘按键s.Remove(data);

                        List<键盘按键.Data> NewKeys = new(键盘按键s);
                        后台任务s.Enqueue(() => 键盘按键.SetData(NewKeys.ToArray(), keydown));
                        Debug.WriteLine(string.Join(',', NewKeys.Select(x => x.Keys)));
                    }
                }
                public static class 键盘按键
                {
                    private static int ID;
                    private static Mutex ___互斥锁;
                    private unsafe static Data* data;
                    private static int maxAppnum = 10;
                    private static int maxArrayLength = 50;
                    private static Mutex[] 工作钥匙 = new Mutex[maxAppnum];
                    private static MemoryMappedFile[] 共享内存 = new MemoryMappedFile[5];
                    private static EventWaitHandle[] 写入事件 = new EventWaitHandle[maxAppnum];

                    static 键盘按键()
                    {
                        ___互斥锁 = new Mutex(false, nameof(键盘按键) + 1, out var createdNew);
                        共享内存[0] = MemoryMappedFile.CreateOrOpen(nameof(键盘按键) + 2, Marshal.SizeOf(typeof(Data)) * maxArrayLength);
                        共享内存[1] = MemoryMappedFile.CreateOrOpen(nameof(键盘按键) + 3, Marshal.SizeOf(typeof(bool)) * maxAppnum);

                        if (createdNew)
                            共享内存[1].CreateViewAccessor().WriteArray(0, new bool[maxAppnum], 0, maxAppnum);

                        if (Process.GetCurrentProcess().ProcessName == "Moyu后台服务")
                        {
                            for (int i = 0; i < maxAppnum; i++)
                            {
                                写入事件[i] = new EventWaitHandle(false, EventResetMode.ManualReset, nameof(键盘按键) + (i + 10));
                                工作钥匙[i] = new Mutex(false, nameof(键盘按键) + (i + 20));
                            }
                        }
                        else
                        {
                            bool[] apps = new bool[maxAppnum];
                            共享内存[1].CreateViewAccessor().ReadArray(0, apps, 0, maxAppnum);

                            ___互斥锁.WaitOne();
                            for (int i = 0; i < maxAppnum; i++)
                                if (!apps[i])
                                {
                                    ID = i;
                                    apps[i] = true;
                                }
                            ___互斥锁.ReleaseMutex();

                            写入事件[ID] = new EventWaitHandle(false, EventResetMode.ManualReset, nameof(键盘按键) + (ID + 10));
                            工作钥匙[ID] = new Mutex(false, nameof(键盘按键) + (ID + 20));
                            工作钥匙[ID].WaitOne();
                        }

                        unsafe
                        {
                            data = GetPtr<Data>(0);
                        }
                    }
                    [MethodImpl(MethodImplOptions.AggressiveOptimization | MethodImplOptions.AggressiveInlining)]
                    public unsafe static List<Data> GetData()
                    {
                        工作钥匙[ID].ReleaseMutex();
                        写入事件[ID].WaitOne();
                        工作钥匙[ID].WaitOne();
                        写入事件[ID].Reset();

                        List<Data> list = new List<Data>();
                        for (int i = 0; i < maxArrayLength; i++)
                        {
                            if (data[i] != default)
                                list.Add(data[i]);
                            else
                                return list;
                        }
                        return list;
                    }
                    [MethodImpl(MethodImplOptions.AggressiveOptimization | MethodImplOptions.AggressiveInlining)]
                    public unsafe static void SetData(Span<Data> datas, bool keydown)
                    {
                        for (int i = 0; i < maxArrayLength; i++)
                        {
                            if (i < datas.Length)
                                data[i] = datas[i];
                            else
                                data[i] = default;
                        }
                        data[0].KeyDown = keydown;

                        for (int i = 0; i < maxAppnum; i++)
                            写入事件[i].Set();

                        for (int i = 0; i < maxAppnum; i++)
                        {
                            工作钥匙[i].WaitOne();
                            工作钥匙[i].ReleaseMutex();
                        }
                    }
                    public unsafe static void Dispose()
                    {
                        工作钥匙[ID].Dispose();
                        写入事件[ID].Dispose();

                        ___互斥锁.WaitOne();
                        bool[] apps = new bool[maxAppnum];
                        共享内存[1].CreateViewAccessor().ReadArray(0, apps, 0, maxAppnum);
                        apps[ID] = false;
                        共享内存[1].CreateViewAccessor().WriteArray(0, apps, 0, maxAppnum);
                        ___互斥锁.ReleaseMutex();

                        foreach (var item in 共享内存)
                        {
                            if (item != null)
                                item.Dispose();
                        }
                        ___互斥锁.Dispose();
                    }
                    public struct Data
                    {
                        public int Keys;
                        public bool KeyDown;
                        public Data(int Keys)
                        {
                            this.Keys = Keys;
                        }
                        public static bool operator ==(Data my1, Data my2)
                        {
                            return my1.Equals(my2);
                        }
                        public static bool operator !=(Data my1, Data my2)
                        {
                            return !(my1 == my2);
                        }
                    }
                    private unsafe static T* GetPtr<T>(int index)
                    {
                        byte* v = default;
                        共享内存[index].CreateViewAccessor().SafeMemoryMappedViewHandle.AcquirePointer(ref v);
                        return (T*)v;
                    }
                }


                private static List<鼠标按键.Data> 鼠标按键s = new();
                private static Dictionary<int, bool> mosePressed = new();
                private static IntPtr MouseProc(int nCode, IntPtr wParam, IntPtr lParam)
                {
                    if (nCode >= 0)
                    {
                        鼠标移动.访问器.Read(0, out 鼠标移动.数据);
                        if (wParam == WM_MOUSEMOVE)
                        {
                            if (鼠标移动.数据.鼠标移动锁)
                                return (IntPtr)1;
                            return CallNextHookEx(_mouseHookHandle, nCode, wParam, lParam);
                        }

                        int button = 0;
                        bool isButtonDown = false;

                        // 处理标准鼠标按钮
                        switch ((uint)wParam)
                        {
                            case WM_LBUTTONDOWN:
                                button = WM_LBUTTONDOWN;
                                isButtonDown = true;
                                break;
                            case WM_LBUTTONUP:
                                button = WM_LBUTTONDOWN;
                                isButtonDown = false;
                                break;
                            case WM_RBUTTONDOWN:
                                button = WM_RBUTTONDOWN;
                                isButtonDown = true;
                                break;
                            case WM_RBUTTONUP:
                                button = WM_RBUTTONDOWN;
                                isButtonDown = false;
                                break;
                            case WM_MBUTTONDOWN:
                                button = WM_MBUTTONDOWN;
                                isButtonDown = true;
                                break;
                            case WM_MBUTTONUP:
                                button = WM_MBUTTONDOWN;
                                isButtonDown = false;
                                break;
                            case WM_MOUSEWHEEL:
                                return CallNextHookEx(_mouseHookHandle, nCode, wParam, lParam);
                            default:
                                // 处理侧键和其他扩展按钮
                                MSLLHOOKSTRUCT hookStruct = (MSLLHOOKSTRUCT)Marshal.PtrToStructure(lParam, typeof(MSLLHOOKSTRUCT));
                                uint mouseData = hookStruct.mouseData;

                                // 侧键处理：通过高位字判断是按下还是抬起
                                if ((mouseData & 0xFFFF0000) != 0)
                                {
                                    button = (int)((mouseData >> 16) & 0xFFFF);
                                    // 根据 flags 或通过其他方式判断按下/抬起状态
                                    // 对于侧键，通常需要根据 wParam 来判断
                                    isButtonDown = IsExtendedButtonDown((uint)wParam);
                                }
                                break;
                        }

                        action(button, isButtonDown);
                    }
                    return CallNextHookEx(_mouseHookHandle, nCode, wParam, lParam);
                    [MethodImpl(MethodImplOptions.AggressiveOptimization | MethodImplOptions.AggressiveInlining)]
                    void action(int keys, bool keydown)
                    {
                        keyPressed[keys] = keydown;
                        鼠标按键.Data data = new(keys);
                        if (keydown)
                            鼠标按键s.Add(data);
                        else
                            鼠标按键s.Remove(data);
                        List<鼠标按键.Data> NewKeys = new(鼠标按键s);
                        后台任务s.Enqueue(() => 鼠标按键.SetData(NewKeys.ToArray(), keydown));
                        Debug.WriteLine(string.Join(',', NewKeys.Select(x => x.Keys)));
                    }
                }
                // 判断扩展按钮（侧键）的按下状态
                [MethodImpl(MethodImplOptions.AggressiveOptimization | MethodImplOptions.AggressiveInlining)]
                private static bool IsExtendedButtonDown(uint wParam)
                {
                    // 侧键的按下消息通常是 XBUTTONDOWN 类型
                    // 需要根据实际的消息值来判断
                    switch (wParam)
                    {
                        case 0x020B: // WM_XBUTTONDOWN
                            Debug.WriteLine("侧键按下");
                            return true;
                        case 0x020C: // WM_XBUTTONUP
                            Debug.WriteLine("侧键抬起");
                            return false;
                        default:
                            // 如果没有明确的按下抬起消息，使用状态切换
                            // 但这可能不r准确，最好使用明确的消息判断
                            return false;
                    }
                }

                [StructLayout(LayoutKind.Sequential)]
                private struct MSLLHOOKSTRUCT
                {
                    public Point pt;
                    public uint mouseData;
                    public uint flags;
                    public uint time;
                    public IntPtr dwExtraInfo;
                }
                private static class 鼠标移动
                {
                    public static string mapName = "Moyu2";
                    public static long 数据大小 = Marshal.SizeOf(typeof(数据s));
                    public static MemoryMappedFile mmf;
                    public static MemoryMappedViewAccessor 访问器;
                    public static 数据s 数据 = new();
                    public struct 数据s
                    {
                        public bool 鼠标移动锁;
                    }
                    public static void 初始化()
                    {
                        mmf = MemoryMappedFile.CreateOrOpen(mapName, 数据大小);
                        访问器 = mmf.CreateViewAccessor();
                    }
                }
                public static class 鼠标按键
                {
                    private static int ID;
                    private static Mutex ___互斥锁;
                    private unsafe static Data* data;
                    private static int maxAppnum = 10;
                    private static int maxArrayLength = 50;
                    private static Mutex[] 工作钥匙 = new Mutex[maxAppnum];
                    private static MemoryMappedFile[] 共享内存 = new MemoryMappedFile[5];
                    private static EventWaitHandle[] 写入事件 = new EventWaitHandle[maxAppnum];

                    static 鼠标按键()
                    {
                        ___互斥锁 = new Mutex(false, nameof(鼠标按键) + 1, out var createdNew);
                        共享内存[0] = MemoryMappedFile.CreateOrOpen(nameof(鼠标按键) + 2, Marshal.SizeOf(typeof(Data)) * maxArrayLength);
                        共享内存[1] = MemoryMappedFile.CreateOrOpen(nameof(鼠标按键) + 3, Marshal.SizeOf(typeof(bool)) * maxAppnum);

                        if (createdNew)
                            共享内存[1].CreateViewAccessor().WriteArray(0, new bool[maxAppnum], 0, maxAppnum);

                        if (Process.GetCurrentProcess().ProcessName == "Moyu后台服务")
                        {
                            for (int i = 0; i < maxAppnum; i++)
                            {
                                写入事件[i] = new EventWaitHandle(false, EventResetMode.ManualReset, nameof(鼠标按键) + (i + 10));
                                工作钥匙[i] = new Mutex(false, nameof(鼠标按键) + (i + 20));
                            }
                        }
                        else
                        {
                            bool[] apps = new bool[maxAppnum];
                            共享内存[1].CreateViewAccessor().ReadArray(0, apps, 0, maxAppnum);

                            ___互斥锁.WaitOne();
                            for (int i = 0; i < maxAppnum; i++)
                                if (!apps[i])
                                {
                                    ID = i;
                                    apps[i] = true;
                                }
                            ___互斥锁.ReleaseMutex();

                            写入事件[ID] = new EventWaitHandle(false, EventResetMode.ManualReset, nameof(鼠标按键) + (ID + 10));
                            工作钥匙[ID] = new Mutex(false, nameof(鼠标按键) + (ID + 20));
                            工作钥匙[ID].WaitOne();
                        }

                        unsafe
                        {
                            data = GetPtr<Data>(0);
                        }
                    }
                    [MethodImpl(MethodImplOptions.AggressiveOptimization | MethodImplOptions.AggressiveInlining)]
                    public unsafe static List<Data> GetData()
                    {
                        工作钥匙[ID].ReleaseMutex();
                        写入事件[ID].WaitOne();
                        工作钥匙[ID].WaitOne();
                        写入事件[ID].Reset();

                        List<Data> list = new List<Data>();
                        for (int i = 0; i < maxArrayLength; i++)
                        {
                            if (data[i] != default)
                                list.Add(data[i]);
                            else
                                return list;
                        }
                        return list;
                    }
                    [MethodImpl(MethodImplOptions.AggressiveOptimization | MethodImplOptions.AggressiveInlining)]
                    public unsafe static void SetData(Span<Data> datas, bool keydown)
                    {
                        for (int i = 0; i < maxArrayLength; i++)
                        {
                            if (i < datas.Length)
                                data[i] = datas[i];
                            else
                                data[i] = default;
                        }
                        data[0].KeyDown = keydown;

                        for (int i = 0; i < maxAppnum; i++)
                            写入事件[i].Set();

                        for (int i = 0; i < maxAppnum; i++)
                        {
                            工作钥匙[i].WaitOne();
                            工作钥匙[i].ReleaseMutex();
                        }
                    }
                    public unsafe static void Dispose()
                    {
                        工作钥匙[ID].Dispose();
                        写入事件[ID].Dispose();

                        ___互斥锁.WaitOne();
                        bool[] apps = new bool[maxAppnum];
                        共享内存[1].CreateViewAccessor().ReadArray(0, apps, 0, maxAppnum);
                        apps[ID] = false;
                        共享内存[1].CreateViewAccessor().WriteArray(0, apps, 0, maxAppnum);
                        ___互斥锁.ReleaseMutex();

                        foreach (var item in 共享内存)
                        {
                            if (item != null)
                                item.Dispose();
                        }
                        ___互斥锁.Dispose();
                    }
                    public struct Data
                    {
                        public int Keys;
                        public bool KeyDown;
                        public Data(int Keys)
                        {
                            this.Keys = Keys;
                        }
                        public static bool operator ==(Data my1, Data my2)
                        {
                            return my1.Equals(my2);
                        }
                        public static bool operator !=(Data my1, Data my2)
                        {
                            return !(my1 == my2);
                        }
                    }
                    private unsafe static T* GetPtr<T>(int index)
                    {
                        byte* v = default;
                        共享内存[index].CreateViewAccessor().SafeMemoryMappedViewHandle.AcquirePointer(ref v);
                        return (T*)v;
                    }
                }


                // 声明钩子处理函数的委托
                private delegate IntPtr LowLevelKeyboardProc(int nCode, int wParam, nint lParam);
                private delegate IntPtr LowLevelMouseProc(int nCode, IntPtr wParam, IntPtr lParam);

                [DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)]
                private static extern IntPtr SetWindowsHookEx(int idHook, LowLevelKeyboardProc lpfn, IntPtr hMod, uint dwThreadId);

                [DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)]
                private static extern IntPtr SetWindowsHookEx(int idHook, LowLevelMouseProc lpfn, IntPtr hMod, uint dwThreadId);

                [DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)]
                private static extern bool UnhookWindowsHookEx(IntPtr hhk);

                [DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)]
                private static extern IntPtr CallNextHookEx(IntPtr hhk, int nCode, IntPtr wParam, IntPtr lParam);


            }
        }
        public class ConcurrentLinkedHashSet<T> : IEnumerable<T> where T : notnull
        {
            protected volatile LinkedHashSet<T> items;
            protected object writeLock = new object();
            public int Count => items.Count;
            public ConcurrentLinkedHashSet()
            {
                this.items = new LinkedHashSet<T>();
            }
            public ConcurrentLinkedHashSet(ICollection<T> items)
            {
                this.items = new LinkedHashSet<T>(items);
            }
            public LinkedHashSet<T> GetHashSet() => new LinkedHashSet<T>(items);
            public void Clear()
            {
                lock (writeLock)
                    this.items = new LinkedHashSet<T>(new HashSet<T>());
            }
            public bool Add(T item)
            {
                lock (writeLock)
                {
                    LinkedHashSet<T> newList = GetHashSet();
                    if (!newList.Add(item))
                        return false;
                    this.items = new LinkedHashSet<T>(newList);
                }
                return true;
            }
            public bool Remove(T item)
            {
                lock (writeLock)
                {
                    LinkedHashSet<T> newList = GetHashSet();
                    if (!newList.Remove(item))
                        return false;
                    this.items = new LinkedHashSet<T>(newList);
                }
                return true;
            }
            public bool Contains(T item)
            {
                lock (writeLock)
                    return this.items.Contains(item);
            }
            public IEnumerator<T> GetEnumerator()
            {
                lock (writeLock)
                    return items.GetEnumerator();
            }
            IEnumerator IEnumerable.GetEnumerator()
            {
                lock (writeLock)
                    return ((IEnumerable)items).GetEnumerator();
            }
        }










    }
}